package com.hqd.jjvm.jnative.reflect;

import com.hqd.jjvm.jnative.JNativeRegistry;
import com.hqd.jjvm.rtda.JThread;
import com.hqd.jjvm.rtda.LocalVars;
import com.hqd.jjvm.rtda.heap.JClass;
import com.hqd.jjvm.rtda.heap.JField;
import com.hqd.jjvm.rtda.heap.JMethod;
import com.hqd.jjvm.rtda.obj.JObject;

public class JNativeConstructorAccessorImplNativeRegistry extends JNativeRegistry {
    private static final JNativeConstructorAccessorImplNativeRegistry instance = new JNativeConstructorAccessorImplNativeRegistry();
    protected static final String CLASS_PATH = "sun/reflect/NativeConstructorAccessorImpl";

    static {
        registry(CLASS_PATH, "newInstance0", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object;", JNativeConstructorAccessorImplNativeRegistry::newInstance0);
    }

    private static void newInstance0(JThread jThread) {
        LocalVars localVars = jThread.getJvmStack().getTop().getLocalVars();
        JObject ref = localVars.getRefVal(0);
        JObject argArrObj = localVars.getRefVal(1);
        JMethod cm = (JMethod) ref.getExtra();
        if (cm == null) {
            JField jf = ref.getJClass().getJField("root", "Ljava/lang/reflect/Constructor;");
            JObject jObject = (JObject) ref.getFields()[jf.getSlotId()].getVal();
            cm = (JMethod) jObject.getExtra();
        }
        JClass jc = cm.getJClass();
        if (!jc.getState().isInit()) {
            JMethod clinit = jc.getJMethod("<clinit>", "()V");
            if (clinit != null) {
                jThread.createStackFrame(clinit);
            }
        }
        JObject newObj = jc.newJObject();
        jThread.getJvmStack().pushOperandStackRefVal(newObj);
        if (cm.getArgSlotCount() == 1 && !cm.isStatic()) {
            jThread.getJvmStack().pushOperandStackRefVal(newObj);
        }
        jThread.createStackFrame(cm);
    }

    public static JNativeConstructorAccessorImplNativeRegistry getInstance() {
        return instance;
    }
}
